package com.example;

import com.example.netty.handler.WebSocketChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * @author zclever <304078606@qq.com>
 * @date 2021-03-02
 */
@Component
public class WebSocketServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);

    @Value("${websocket.port}")
    private int port;

    @Autowired
    private WebSocketChannelInitializer webSocketChannelInitializer;

    public void start() throws Exception {
        //创建主线程组，接收请求
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //创建从线程组，处理主线程组分配下来的io操作
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        //创建netty服务器
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap
                    //设置主从线程组
                    .group(bossGroup, workerGroup)
                    //设置通道
                    .channel(NioServerSocketChannel.class)
                    //设置日志
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    //子处理器，用于处理workerGroup中的操作
                    .childHandler(webSocketChannelInitializer);
            //启动server
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            logger.info("websocket服务端启动成功,端口:{}",port);

            //监听关闭channel
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();//关闭主线程
            workerGroup.shutdownGracefully();//关闭从线程
        }
    }
}